V nekem podjetju zbirajo podatke o osebah, ki brskajo po medmrežju. Podatki so shranjeni v slovarjih (en slovar za vsako osebo). Ključ v takem slovarju je lastnost, vrednosti pa podatek o tej lastnosti za določeno osebo. Primeri takšnih slovarjev:
oseba1 = {'ime': 'Božidar', 'telefon': '031918211',
'obiskane spletne strani': ['facebook.com', 'google.com']}
oseba2 = {'naslov': 'Dunajska 105', 'številka noge': 42,
'prijatelji': ['Marko', 'Ana']}
Sestavite funkcijo podatek(oseba, lastnost)
, ki vrne podatek o
lastnosti lastnost
, ki ga imamo v slovarju oseba
. Funkcija naj vrne
None
, če se ta podatek v slovarju ne nahaja. Primer:
>>> podatek({'ime': 'Božidar', 'naslov': 'Dunajska 105'}, 'naslov')
'Dunajska 105'
>>> podatek({'ime': 'Božidar', 'naslov': 'Dunajska 105'}, 'prijatelji')
None
Pri tem ne smeš uporabiti get!
def podatek(oseba, lastnost): '''Vrne podatek o lastnosti lastnost oz. None''' if lastnost not in oseba: return None return oseba[lastnost]
Sestavite funkcijo podatekGet(oseba, lastnost)
, ki vrne podatek o
lastnosti lastnost
, ki ga imamo v slovarju oseba
. Funkcija naj vrne
None
, če se ta podatek v slovarju ne nahaja. Primer:
>>> podatekGet({'ime': 'Božidar', 'naslov': 'Dunajska 105'}, 'naslov')
'Dunajska 105'
>>> podatekGet({'ime': 'Božidar', 'naslov': 'Dunajska 105'}, 'prijatelji')
None
Pri tem si nujno pomagajte z metodo get
def podatekGet(oseba, lastnost): '''Vrne podatek o lastnosti lastnost oz. None''' return oseba.get(lastnost, None)
Za osebi oseba1
in oseba2
pravimo, da se ujemata v lastnosti
lastnost
, če za obe osebi poznamo podatka o tej lastnosti in sta
podatka enaka. Če pa za obe osebi poznamo podatka in sta podatka
različna, pa pravimo, da se osebi razlikujeta v lastnosti lastnost
.
Na primer, osebi
oseba1 = {'ime': 'Janez', 'priimek': 'Novak'}
oseba2 = {'ime': 'Jože', 'priimek': 'Novak', 'starost': 20}
se ujemata v lastnosti 'priimek'
in razlikujeta v lastnosti 'ime'
.
(V lastnosti 'starost'
se niti ne ujemata niti ne razlikujeta.)
Sestavite funkcijo ujemanje(oseba1, oseba2)
, ki pove, v koliko
lastnostih se osebi oseba1
in oseba2
ujemata in v koliko lastnostih
se razlikujeta. Rezultat naj funkcija vrne kot seznam z dvema elementoma.
Primer:
>>> ujemanje({'ime': 'Janez', 'priimek': 'Novak'},
{'ime': 'Jože', 'priimek': 'Novak', 'starost': 20})
[1, 1]
def ujemanje(oseba1, oseba2): '''V koliko lastnostih se osebi ujemata in razlikujeta''' ujema = 0 razlikuje = 0 for lastnost in oseba1: # preverimo vse lastnosti prve osebe if lastnost in oseba2: # če gre za skupno lastnost if oseba1[lastnost] == oseba2[lastnost]: ujema += 1 else: razlikuje += 1 return [ujema, razlikuje]
Dva različna slovarja oseba1
in oseba2
lahko predstavljata isto
osebo. To se zgodi, če se slovarja ne razlikujeta v več kot 1 lastnosti
in se ujemata vsaj v 3 lastnostih ali če sta v obeh slovarjih lastnosti
ime
in priimek
enaki. Na primer, slovarja
oseba1 = {'ime': 'Janez', 'priimek': 'Novak', 'telefon': '031123234',
'starost': 90}
oseba2 = {'ime': 'Janez', 'priimek': 'Novak', 'davčna': '43424140'}
predstavljata isto osebo, prav tako slovarja
oseba1 = {'ime': 'Janez', 'priimek': 'Novak', 'telefon': '031123234',
'starost': 90}
oseba2 = {'ime': 'Luka', 'priimek': 'Novak', 'starost': 90,
'davčna': '43424140', 'telefon': '031123234'}
Sestavite funkcijo ista(oseba1, oseba2)
, ki preveri, ali slovarja
predstavljata isto osebo. Na primer, za zgornja primera mora funkcija
vrniti True
.
def ista(oseba1, oseba2): '''Ali gre ta isto osebo''' ujemata, razlikujeta = ujemanje(oseba1, oseba2) # uporaba funkcije prejšnje naloge je_ista = ujemata >= 3 and razlikujeta <= 1 if je_ista : return True # dovolj je že ujemanje v lastnostih! # če ni ujemanja v lastnostih, preverimo ime in priimek if 'ime' in oseba1 and 'ime' in oseba2 and 'priimek' in oseba1 and 'priimek' in oseba2: je_ista = (oseba1['ime'] == oseba2['ime'] and oseba1['priimek'] == oseba2['priimek']) return je_ista
V seznamu slovarjev, ki predstavljajo osebe, se lahko zgodi, da več slovarjev predstavlja isto osebo (isto v smislu prejšnje podnaloge). V takem primeru pravimo, da so ti slovarji podvojeni.
Sestavite funkcijo podvojeni(s)
, ki vrne seznam vseh podvojenih
slovarjev iz seznama s
. Slovarji naj bodo razvrščeni v istem vrstnem
redu kot v seznamu s
. Primer:
>>> podvojeni([{'ime': 'Jan', 'priimek': 'Dan', 'naslov': 'Jadranska 21'},
{'ime': 'Jan', 'priimek': 'Dan', 'naslov': 'Jadranska 19'},
{'ime': 'Žan', 'priimek': 'Dan', 'naslov': 'Jadranska 21'},
{'ime': 'Žan', 'priimek': 'Noč', 'naslov': 'Jamova 25'}])
[{'ime': 'Jan', 'priimek': 'Dan', 'naslov': 'Jadranska 21'},
{'ime': 'Jan', 'priimek': 'Dan', 'naslov': 'Jadranska 19'}]
def jeOsebaPodvojena(osb, s): '''Ali se oseba osb pojavi v seznamu s vsaj dvakrat''' kolikoIstih = 0 for oseba2 in s: # pogledamo vse osebe slovarja s if ista(osb, oseba2): # gre za isto osebo po kriterijih prej kolikoIstih += 1 return kolikoIstih >= 2 def podvojeni(s): '''Seznam vseh podvojenih oseb''' seznam = [] for oseba in s: # vsako osebo if jeOsebaPodvojena(oseba, s): # prevrimo, če je v seznamu oseba vsaj 2x seznam.append(oseba) return seznam
Sestavine, ki jih potrebujemo za nek recept, opišemo s slovarjem, v katerem so ključi sestavine, vrednosti pa količine, ki jih potrebujemo.
Sestavite funkcijo pomnozi(recept, faktor)
, ki sestavi in vrne nov
recept. Ta naj vsebuje iste sestavine kot recept recept
, le da so vse
količine v njem pomnožene z danim faktorjem.
>>> pomnozi({'jajca': 4, 'moka': 500}, 2)
{'jajca': 8, 'moka': 1000}
def pomnozi(recept, faktor): '''Vrne nov recept, spremenjen za faktor''' novR = dict() for sestavina, kolicina in recept.items(): novR[sestavina] = kolicina * faktor return novR def pomnoziV2(recept, faktor): '''Vrne nov recept, spremenjen za faktor''' # uporabimo izpeljane slovarje (dict comprehension) return {sestavina: kolicina * faktor for sestavina, kolicina in recept.items()}
Sestavite funkcijo imamoSestavine(recept, shramba)
, ki preveri, ali
imamo v shrambi dovolj sestavin za dani recept. Sestavine, ki jih imamo
v shrambi, so predstavljene s slovarjem na enak način kot sestavine v
receptu.
def imamoSestavine(recept, shramba): '''imamo v shrambi dovolj sestavin za dani recept''' for sestavina, kolicina in recept.items(): if shramba.get(sestavina, -1) < kolicina: # uporaba get, da ne dobimo izjeme pri neobstoječih sestavinah return False # že če ena manjka, ne gre return True # vsega imamo dovolj!
Sestavite funkcijo potrebnoKupiti(recept, shramba)
, ki vrne slovar
sestavin s pripadajočimi količinami, ki jih moramo še dokupiti, da bomo
lahko skuhali jed po danem receptu.
>>> potrebnoKupiti({'jajca': 3, 'moka': 500}, {'moka': 1000, 'jajca': 6, 'sladkor': 1000})
{}
>>> potrebnoKupiti({'jajca': 3, 'moka': 500}, {'moka': 1000, 'sladkor': 1000})
{'jajca': 3}
>>> potrebnoKupiti({'jajca': 3, 'moka': 500}, {'moka': 100})
{'jajca': 2, 'moka': 400}
def potrebnoKupiti(recept, shramba): '''vrne slovar sestavin s pripadajočimi količinami, ki jih moramo še dokupiti, da bomo lahko skuhali jed po danem receptu.''' kupiti = dict() for sestavina, kolicina in recept.items(): razlika = kolicina - shramba.get(sestavina, 0) # če sestavine še nimamo, je enako, kot če jo imamo 0! if razlika > 0: kupiti[sestavina] = razlika return kupiti
Niz je antipalindrom, kadar ima znake na vseh mestih različne od svojega
obrata. Tako je beseda mama
antipalindrom, saj se noben znak ne ujema
z znakom na istem mestu v besedi amam
, beseda anketa
pa ni antipalindrom,
saj ima prvem in zadnjem mestu enako črko kot njen obrat atekna
.
Sestavite funkcijo jeAntipalindrom(niz)
, ki vrne True
, če je niz
antipalindrom, in False
če ni.
def jeAntipalindrom(niz): '''Ali je niz antipalnidrom''' dolNiz = len(niz) if dolNiz % 2 == 1: # vsi lihi nizi zagotovo niso antipalidromi! return False for ind in range(dolNiz // 2): # preverimo prvih pol znakov (pazi if niz[ind] == niz[dolNiz - 1 - ind] : # primerjamo znake začetnega in končnega dela return False return True # vsi Testi so bili uspešni def jeAntipalindromV2(niz): '''Ali je niz antipalnidrom''' # uporaba naprednejših metod # V dokumentaciji si oglej all in zip return all(z1 != z2 for z1, z2 in zip(niz, niz[::-1]))
Sestavite funkcijo vsebovaniAntipalindromi(niz)
, ki vrne množico vseh
strnjenih podnizov niza niz
, ki so antipalindromi.
def vsebovaniAntipalindromi(niz): '''Vrne množico podnizov niza niz, ki so antipalindromi''' antipalindromi = set() # naredimo vse možne podnize for i in range(len(niz)): for j in range(i + 1, len(niz)+1): podniz = niz[i:j] # uporabimo funkcijo gornje naloge if jeAntipalindrom(podniz): # je anitiPalindrom, ga dodamo antipalindromi.add(podniz) return antipalindromi
Za razliko od običajnih družabnih omrežij, deluje nedružabno omrežje Hatebook tako, da si v omrežje vsak dodaja svoje sovražnike. Omrežje predstavimo s slovarjem, pri čemer so ključi osebe, vrednosti pa množice oseb, ki jih te osebe sovražijo.
Sestavite funkcijo seSovrazita(omrezje, oseba1, oseba2)
, ki vrne True
,
kadar osebi sovražita druga drugo, in False
sicer.
def seSovrazita(omrezje, oseba1, oseba2): '''Ali se osebi sovražita''' # oba ključa morata biti v seznamu vrednosti za drug ključ! return oseba1 in omrezje[oseba2] and oseba2 in omrezje[oseba1]
Sestavite funkcijo kdoSovrazi(omrezje, oseba)
, ki vrne množico oseb,
ki v danem omrežju sovražijo dano osebo.
def kdoSovrazi(omrezje, oseba): '''vrne množico oseb, ki v danem omrežju sovražijo dano osebo ''' kdoSovraži = set() for sovrag, sovrazniki in omrezje.items(): if oseba in sovrazniki: kdoSovraži.add(sovrag) return kdoSovraži def kdoSovraziV2(omrezje, oseba): '''vrne množico oseb, ki v danem omrežju sovražijo dano osebo ''' # uporaba izpeljanih množic (set comprehension) return {sovrag for sovrag, sovrazniki in omrezje.items() if oseba in sovrazniki}
Sestavite funkcijo nesrecniki(omrezje)
, ki vrne množico oseb, ki
sovražijo same sebe.
def nesrecniki(omrezje): '''Vrne množico oseb, ki sovražijo sebe''' mnNesrečnikov = set() for oseba, sovrazniki in omrezje.items(): if oseba in sovrazniki: mnNesrečnikov.add(oseba) return mnNesrečnikov def nesrecnikiV2(omrezje): '''Vrne množico oseb, ki sovražijo sebe''' # uporaba izpeljanih množic return {oseba for oseba, sovrazniki in omrezje.items() if oseba in sovrazniki}
Sestavite funkcijo najboljZadrti(omrezje)
, ki vrne množico vseh oseb,
ki v danem omrežju sovražijo največ oseb.
def najboljZadrti(omrezje): '''vrne množico vseh oseb, ki v danem omrežju sovražijo največ oseb''' najvec = 0 for sovrazniki in omrezje.values(): najvec = max(len(sovrazniki), najvec) # večjega od trenutnega kandidata in naj doslej # in še izpeljanih množic mnZadrtih = set() for oseba, sovrazniki in omrezje.items(): if len(sovrazniki) == najvec: mnZadrtih.add(oseba) return mnZadrtih def najboljZadrtiV2(omrezje): '''vrne množico vseh oseb, ki v danem omrežju sovražijo največ oseb''' #uporaba izpeljaniega ponovnika najvec = max(len(sovrazniki) for sovrazniki in omrezje.values()) # in še izpeljanih množic return {oseba for oseba, sovrazniki in omrezje.items() if len(sovrazniki) == najvec}
Sestavite funkcijo unijaSlovarjev(seznam_slovarjev)
, ki bo iz
danega seznama slovarjev sestavila nov slovar, ki bo predstavljal
unijo posameznih slovarjev. Vrednosti ključev v uniji slovarjev naj bodo
seznami vrednosti, ki pripadajo enakim ključem iz vhodnih slovarjev. Vrednosti naj bodo v
seznamih zapisane v enakem vrstnem redu, kot nastopajo v seznamu slovarjev.
Zgled:
>>> unija_slovarjev([{1: 2, 5: 0}, {2: 3, 5: 6, 7: 3}, {2: 3, 8: 1, 5: 4}])
{1: [2], 5: [0, 6, 4], 2: [3, 3], 7:[3], 8:[1]}
def unijaSlovarjev(seznamSlovarjev): '''Vrnemo slovar, ki je unija slovarjev''' novSlovar = dict() for slovar in seznamSlovarjev: # obdelamo vse slovarje for kljuc in slovar: if kljuc in novSlovar: # če se je ta ključ že pojavil novSlovar[kljuc].append(slovar[kljuc]) # dodamo njegovo vrednost else: novSlovar[kljuc] = [slovar[kljuc]] # sicer pa je to nov ključ return novSlovar
Patrik je za vse električne naprave, ki jih ima doma, ugotovil ime proizvajalca in podatke shranil v slovar. Zgled takega slovarja:
naprave = {
'hladilnik': 'Gorenje', 'pralni stroj': 'Whirlpool',
'kavni mlinček': 'Bosch', 'mikrovalovna pečica': 'Gorenje',
'parni čistilnik': 'Philips', 'laserski tiskalnik': 'Lexmark',
'sušilnik las': 'Philips'
}
Njegov sosed Darko pa je iz čistega dolgčasa sestavil slovar, v katerem so ključi naprave, vrednosti pa kategorije, kamor te naprave sodijo. Zgled:
kategorije = {
'hladilnik': 'bela tehnika', 'parni čistilnik': 'sesalniki',
'grelnik vode': 'kuhinjski aparati', 'pralni stroj': 'bela tehnika',
'sušilnik las': 'nega las', 'mikrovalovna pečica': 'kuhinjski aparati',
'laserski odstranjevalec dlačic': 'brivniki in depilatorji'
}
Patrik in Darko bi rada združila podatke in za vsako blagovno znamko,
ki se pojavi v Patrikovem slovarju, ugotovila, katere kategorije naprav
"pokriva" glede na Darkov slovar. Napišite funkcijo
blagovne_znamke(naprave, kategorije)
, ki vrne slovar, kjer so ključi
imena proizvajalcev, njihove pripadajoče vrednosti pa so množice
kategorij, s katerimi se proizvajalec ukvarja.
Naj bosta slovarja naprave
in kategorije
enaka kot zgoraj. Zgled:
>>> blagovne_znamke(naprave, kategorije)
{'Lexmark': set(), 'Philips': {'sesalniki', 'nega las'}, 'Whirlpool': {'bela tehnika'},
'Gorenje': {'bela tehnika', 'kuhinjski aparati'}, 'Bosch': set()}
Bodite pozorni na to, da se lahko v Patrikovem slovarju pojavijo tudi naprave, ki jih Darko nima v svojem slovarju, in obratno.
def blagovne_znamke(naprave, kategorije): '''vrne slovar, kjer so ključi imena proizvajalcev, njihove pripadajoče vrednosti pa so množice kategorij, s katerimi se proizvajalec ukvarja.''' blagZnamke = dict() for naprava, znamka in naprave.items(): if znamka not in blagZnamke: blagZnamke[znamka] = set() # nova znamka, začnemo s prazno množico if naprava in kategorije: blagZnamke[znamka].add(kategorije[naprava]) # dodamo vse ustrezne kategorije return blagZnamke
Dan je slovar, ki slika ključe xi
(ključi so nizi)
v celoštevilske vrednosti vi
, recimo
{'foo':1, 'bar':7, 'baz':100, 'qux':20, 'quux':30}
Sestavi funkcijo ključZNajVrednostjo(sl)
, ki sprejme tak slovar
in vrne tisti ključ xi
, ki ima
največjo pripadajočo vrednost vi
. Če bi na primer poklicali funkcijo
s prejšnjim slovarjem, bi dobili rezultat 'baz'
.
Če je slovar prazen, vrni None
.
Predpostavi, da je le en ključ z največjo vrednostjo.
def ključZNajVrednostjo(sl): ''' vrne tisti ključ `xi`, ki ima največjo pripadajočo vrednost `vi`.''' if not sl: # če je prazen return None # za kandidata vzamemo vrednost prvega iz slovarja for kl, vr in sl.items(): najVr = vr najKljuč = 'Žal bom izginil' break # rabimo le prvega # sedaj pa zares for kl, vr in sl.items(): if vr >= najVr: # našli smo boljšega najVr = vr najKljuč = kl return najKljuč
Sedaj pa spustimo omejitev, da obstaja le en ključ z največjo vrednostjo.
Sestavi funkcijo seznamKljučevZNajVrednostjo(sl)
, ki vrne po
abecedi urejen seznam vseh ključev z največjo vrednostjo.
Če je slovar prazen, vrni prazen seznam.
def seznamKljučevZNajVrednostjo(sl): ''' vrne po abecedi urejen seznam tisti ključev `xi`, ki imajo največjo pripadajočo vrednost `vi`.''' if not sl: # če je prazen return [] # za kandidata vzamemo vrednost prvega iz slovarja - 1 for kl, vr in sl.items(): najVr = vr - 1 najKljuč = [] break # rabimo le prvega # sedaj pa zares for kl, vr in sl.items(): if vr > najVr: # našli smo boljšega najVr = vr najKljuč = [kl] elif vr == najVr: # našli smo enako dobrega najKljuč.append(kl) return sorted(najKljuč)
prosto po Tavčarju ;-) ali po Galetu
Socialno omrežje zaljubljenosti podamo s slovarjem, ki ime osebe preslika v seznam vseh, v katere je oseba zaljubljena (ena oseba je lahko zaljubljena v več oseb). Na primer, slovar
s = {'Ana' : ['Bine','Cene'],
'Bine' : [],
'Cene' : ['Bine', 'Cene'],
'Davorka' : ['Davorka'],
'Eva' : ['Bine']}
nam pove, da je Ana zaljubljena v Bineta in Cenete, Bine ni zaljubljen, Cene ljubi Bineta in samega sebe, Davorka samo sebe in Eva Bineta.
Sestavite funkcijo narcisoidi(d)
, ki sprejme slovar zaljubljenih
in vrne po abecedi urejen seznam tistih, ki ljubijo same sebe.
def narcisoidi(d): '''Vrne po abecedi urejen seznam narcisoidov''' sezNar = [] for oseba in d: if oseba in d[oseba]: # ta bo pravi! sezNar.append(oseba) return sorted(sezNar) def narcisoidiV2(d): '''Vrne po abecedi urejen seznam narcisoidov''' # uporabimo izpeljane sezname (list comprehension) return sorted([oseba for oseba in d if oseba in d[oseba]])
Sestavite funkcijo ljubljeni(d)
, ki sprejme slovar zaljubljenih
in vrne po abecedi urejen seznam tistih, ki so ljubljeni.
def ljubljeniV2(d): '''Vrne po abecedi urejen _seznam_ tistih, ki so ljubljeni''' # naredimo s seznamom seznamOseb = list() for oseba in d: # za vse osebe for ljubljen in d[oseba]: # dodamo njihove ljubljene (če je potrebno) if ljubljen not in seznamOseb: # če še niso seznamOseb.append(ljubljen) return sorted(seznamOseb) def ljubljeni(d): '''Vrne po abecedi urejen _seznam_ tistih, ki so ljubljeni''' mnLjubljenih = set() for oseba in d: # za vse osebe mnLjubljenih.update(d[oseba]) # dodamo vse ljubljene te osebe return sorted(mnLjubljenih) # sorted vrne urejen seznam - argument je lahko poljubni iterator
Sestavite funkcijo pari(d)
, ki sprejme slovar zaljubljenih
in vrne seznam vseh parov, ki so srečno ljubljeni. Vsak
par naj se pojavi samo enkrat in sicer tako, da je sta zaljubljenca
našteta po abecedi. Na primer, če sta Ana in Bine zaljubljena,
dodamo par ('Ana','Bine')
.
def pari(d): '''Po abecedi urejen par srečno ljubljenih - torej takioh, ki ljubijo osebo, ki ljubi njih''' seznamParov = [] for oseba in d: # za vsako osebo, ki jo ljubi, pogledamo, če ta ljubi njega for ljubljeni in d[oseba]: if oseba in d[ljubljeni] : # ga bomo dodali urejenPar = tuple(sorted([oseba,ljubljeni])) # a le , če že ni notri if urejenPar not in seznamParov: # namig - namesto seznama bi lahko uporabili množico in bi ta stavek if odpadel seznamParov.append(urejenPar) return sorted(seznamParov)
Sestavite funkcijo ustrezljivi(oseba, d)
, ki sprejme ime osebe ter
slovar zaljubljenih, vrne pa po abecedi urejen seznam vseh ljudi, ki so do dane osebe
še posebej ustrežljivi. Posebej ustrežljivi so seveda za to, ker so
bodisi zaljubljeni v dano osebo, bodisi so zaljubljeni v osebo, ki je
posebej ustrežljiva do nje, in tako naprej.
Na primer, če imamo slovar
s = {'Ana' : ['Bine', 'Cene'],
'Bine' : ['Ana'],
'Cene' : ['Bine'],
'Davorka' : ['Davorka'],
'Eva' : ['Bine']}
so do Ceneta posebej ustrežljivi Ana (ki je zaljubljena vanj), Bine (ki je zaljubljen v Ano), Eva (ki je zaljubljena v Bineta), ter seveda Cene, ki je zaljubljen v Evo.
def ustrezljiviV2(oseba, d): '''vrne po abecedi urejen _seznam_ vseh ljudi, ki so do dane osebe še posebej ustrežljivi''' # seznam, v katerega nabiramo ustrežljive osebe ustrezljivi = [] # najprej dodamo tiste, ki ljubijo prvo osebo dodani = [o for o in d if oseba in d[o]] # dokler smo koga dodali, dodajamo ustrežljive while dodani: for nekdo in dodani: if nekdo not in ustrezljivi: # če ga še ni noter ustrezljivi.append(nekdo) # sedaj pa dodajamo tiste, ki ljubijo nazadnje dodane osebe dodani = [o for o in d for dodan in dodani if dodan in d[o] and o not in ustrezljivi] return sorted(ustrezljivi) def ustrezljivi(oseba, d): '''vrne po abecedi urejen _seznam_ vseh ljudi, ki so do dane osebe še posebej ustrežljivi''' # seznam, v katerega nabiramo ustrežljive osebe ustrezljivi = [] # najprej dodamo tiste, ki ljubijo prvo osebo dodani = [] for nekdo in d: if oseba in d[nekdo]: dodani.append(nekdo) # dokler smo koga dodali, dodajamo ustrežljive while dodani: for nekdo in dodani: if nekdo not in ustrezljivi: # če ga še ni noter ustrezljivi.append(nekdo) # sedaj pa dodajamo tiste, ki ljubijo nazadnje dodane osebe noviDodani = [] for o in d: for nekdo in dodani: if nekdo in d[o] and o not in ustrezljivi: noviDodani.append(o) dodani = noviDodani[:] return sorted(ustrezljivi)
Pri tej nalogi boste napisali funkcijo, ki bo za dano število vrnila niz z ustrezno rimsko številko. Nato boste napisali še funkcijo, ki bo rimsko številko spremenila nazaj v število.
Preden začnete, si na oglejte članek o rimskih številkah na Wikipediji: Rimske številke.
Napišite funkcijo vRimsko(stevilo)
, ki kot argument dobi celo
število med 1 in 3999 (vključno z 1 in 3999). Funkcija naj sestavi
in vrne niz, ki vsebuje rimsko številko, ki predstavlja število stevilo
.
Zgled:
>>> vRimsko(2013)
'MMXIII'
def vRimsko(stevilo): '''Iz 'običajnega' zapisa števila med 1 in 3999 naredimo rimski zapis števila ''' tabelaRimskih = [ ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'], ['', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'], ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'], ['', 'M', 'MM', 'MMM']] rimsko = '' for i in range(4): rimsko = tabelaRimskih[i][stevilo%10] + rimsko stevilo //= 10 return rimsko
Napišite še funkcijo vArabsko(niz)
, ki bo dobila niz niz
, ki
predstavlja rimsko številko. Funkcija naj naredi ravno obratno kot
funkcija vRimsko
, tj. vrne naj ustrezno število, ki ga predstavlja
dana rimska številka. Če niz
ne predstavlja veljavnege rimske
številke, naj funkcija vrne None
. Zgled:
>>> vArabsko('MMXIII')
2013
Nasvet: Najprej sestavi slovar, ki kot ključe vsebuje rimske številke, kot vrednosti pa ustrezna števila. Potem le uporabi ta slovar.
def vArabsko(niz): '''Iz rimskega zapisa naredimo arabski zapis števila Če ne gre, vrnemo None. ''' tabelaRimskih = [ ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'], ['', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'], ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'], ['', 'M', 'MM', 'MMM']] slovarRimskih = {vRimsko(i):i for i in range(1, 4000)} if niz not in slovarRimskih: return None return slovarRimskih[niz]
Ukvarjali se bomo z rodovniki (Celjskih grofov in drugih). Rodovnik imamo podan kot slovar, kjer je ključ ime "glave rodbine" vrednost pa seznam imen otrok. Recimo:
rodovnik =
{'Ulrik I.': ['Viljem'], 'Margareta': [], 'Herman I.': ['Herman II.', 'Hans'],
'Elizabeta II.': [], 'Viljem': ['Ana Poljska'], 'Elizabeta I.': [],
'Ana Poljska': [], 'Herman III.': ['Margareta'], 'Ana Ortenburška': [],
'Barbara': [], 'Herman IV.': [], 'Katarina': [], 'Friderik III.': [],
'Herman II.': ['Ludvik', 'Friderik II.', 'Herman III.', 'Elizabeta I.', 'Barbara'],
'Ulrik II.': ['Herman IV.', 'Jurij', 'Elizabeta II.'], 'Hans': [], 'Ludvik': [],
'Friderik I.': ['Ulrik I.', 'Katarina', 'Herman I.', 'Ana Ortenburška'],
'Friderik II.': ['Friderik III.', 'Ulrik II.'], 'Jurij': []}
rodovnik['Friderik II.']
nam torej vrne
['Friderik III.', 'Ulrik II.']
Število otrok
Sestavi funkcijo kolikoOtrok(ime, rodovnik)
, ki za dano ime in
rodovnik vrne število otrok te osebe, oz None, če osebe ni v rodovniku.
def kolikoOtrok(ime, rodovnik) : ''' koliko otrok ima oseba z imenom ime ''' if ime not in rodovnik: return None return len(rodovnik[ime])
Število potomcev
Sestavi funkcijo kolikoPotomcev(ime, rodovnik)
, ki za dano ime
in
rodovnik
vrne število potomcev te osebe. Če osebe ni v rodovniku, vrni None
def kolikoPotomcev(ime, rodovnik) : ''' koliko potomcev ima oseba z imenom ime ''' if ime not in rodovnik: # če je slučajno ni return None otroci = rodovnik[ime] kolikoJihJe = len(otroci) # potomci so otroci for oseba in otroci: # in vsi potomci otrok kolikoJihJe += kolikoPotomcev(oseba, rodovnik) return kolikoJihJe
Je v rodbini?
Sestavi funkcijo jeTaVRodbini(ime, glavaRodbine, rodovnik)
, ki ugotovi, ali
je oseba z imenom ime
v rodbini osebe glavaRodbine
.
def jeTaVRodbini(ime, glavaRodbine, rodovnik) : ''' Ali je oseba z imenom ime v rodbini osebe glavaRodbine ''' if ime == glavaRodbine: # če je to že kar "šef" return True # je morda med otroci otroci = rodovnik[glavaRodbine] if ime in otroci : # pravzaprav je ta stavek if odveč. Zakaj? Premisli! return True # je morda v rodbini otrok? for oseba in otroci : if jeTaVRodbini(ime, oseba, rodovnik) : return True # ni bil nikjer, torej ... return False
Kdo se podpisuje najdlje časa?
Sestavi funkcijo najdaljsiPodpis(glavaRodbine, rodovnik)
, ki ugotovi, kdo
v rodbini osebe glavaRodbine
ima najdaljše ime za podpis (torej kompletno ime).
def najdaljsiPodpis(glavaRodbine, rodovnik) : ''' kdo v rodbini osebe glavaRodbine ima najdaljše ime. ''' najIme = glavaRodbine # morda je to kar glava rodbine # je morda v rodbini otrok? otroci = rodovnik[glavaRodbine] for oseba in otroci : najMedOsebo = najdaljsiPodpis(oseba, rodovnik) if len(najMedOsebo) > len(najIme) : najIme = najMedOsebo return najIme
Kdo ima najkrajše ime?
Sestavi funkcijo najkrajseIme(glavaRodbine, rodovnik)
, ki ugotovi, kdo
v rodbini osebe glavaRodbine
ima najkrajše ime.
(šteje samo krstno ime, brez "Ortenburga" in "Celja" ter brez številk)?
def najkrajseIme(glavaRodbine, rodovnik) : ''' kdo v rodbini osebe glavaRodbine ima najkrajse ime. ''' # morda je to kar glava rodbine najIme = glavaRodbine.split()[0] # izrabimo dejstvo, da je "pravo" ime takoj na začetku ... # je morda v rodbini otrok? otroci = rodovnik[glavaRodbine] for oseba in otroci : najMedOsebo = najkrajseIme(oseba, rodovnik) if len(najMedOsebo) < len(najIme) : najIme = najMedOsebo return najIme
Globina rodbine
"Globino" rodbine definiramo tako: če nekdo nima otrok, je globina njegove rodbine 1. Če ima otroka, ta pa nima vnukov (ali celo več otrok, ti pa nimajo vnukov), je globina rodbine 2. Če nekdo ima vnuke, vendar nobenega pravnuka, je globina njegove rodbine 3.
Sestavi funkcijo globina(glavaRodbine, rodovnik)
, ki vrne globino rodbine
osebe glavaRodbine
v rodovniku rodovnik
def globina(glavaRodbine, rodovnik): '''Kakšna je globina rodbine osebe glavaRodbine''' # če nima otrok, je na globini 1 if rodovnik[glavaRodbine] == []: return 1 # ima vsaj enega otroka # potrebujemo globine vseh otrok te glaveRodbine glOtrok = [] for otrok in rodovnik[glavaRodbine]: # koliko je globina za tega otroka glOtroka = globina(otrok, rodovnik) glOtrok.append(glOtroka) # zanima nas le največja najGlOtrok = max(glOtrok) # globina glave rodbine je za 1 večja od tega maksimuma return 1 + najGlOtrok def globinaV2(glavaRodbine, rodovnik): '''Kakšna je globina rodbine osebe glavaRodbine brez uporabe funkcije max ''' # če nima otrok, je na globini 1 if rodovnik[glavaRodbine] == []: return 1 # ima vsaj enega otroka # potrebujemo maksimalno globino od vseh otrok te glaveRodbine najGlOtrok = 0 # ker so vse globine poz. števila, je začetni kandidat lahko 0 for otrok in rodovnik[glavaRodbine]: # koliko je globina za tega otroka glOtroka = globinaV2(otrok, rodovnik) if glOtroka > najGlOtrok: # našli smo boljšega kandidata najGlOtrok = glOtroka # globina glave rodbine je za 1 večja od tega maksimuma return 1 + najGlOtrok def globinaV3(oseba, rodovnik): otroci = rodovnik[oseba] if otroci: # če imamo otroke, je naša globina za 1 večja od naj globine naših otrok return 1 + max(globinaV3(otrok, rodovnik) for otrok in otroci) else: # drugače smo na globini 1 return 1